#ifndef __MY_DATA__
#define __MY_DATA__
#include "util.hpp"
#include <cstdlib>
#include <mutex>
#include <mysql/mysql.h>

namespace aod{
#define HOST "127.0.0.1"
#define USER "root"
#define PASS "zyl0126."
#define NAME "aod_system"
    //mysql的封装
    //初始化
	static MYSQL *MysqlInit() {
		//1初始化句柄
		MYSQL *mysql = mysql_init(NULL);
		if (mysql == NULL) {
			std::cout << "init mysql instance failed!\n";
			return NULL;
		}
		//2 链接服务器
		if (mysql_real_connect(mysql, HOST, USER, PASS, NAME, 0, NULL, 0) == NULL) {
			std::cout << "connect mysql server failed!\n";
			mysql_close(mysql);
			return NULL;
		}
		// 3设置客户端字符集
		mysql_set_character_set(mysql, "utf8");
		return mysql;
	}
	//销毁
	static void MysqlDestroy(MYSQL *mysql) {
		if (mysql != NULL) {
			mysql_close(mysql);
		}
		return;
	}
	//执行语句
	static bool MysqlQuery(MYSQL *mysql, const std::string &sql) {
		int ret = mysql_query(mysql, sql.c_str());
		if (ret != 0) {
			std::cout<<"执行"<<sql<<"语句失败"<<std::endl;
            std::cout<<"错误信息"<<mysql_errno(mysql) <<std::endl;
			return false;
		}
		return true;
	}
	class TableVideo{
		private:
			MYSQL *_mysql;		// ⼀个对象就是⼀个客⼾端，管理⼀张表
			std::mutex _mutex;	// 防备操作对象在多线程中使⽤存在的线程安全 问题
		public:
			// 完成mysql句柄初始化
			TableVideo() {
				_mysql = MysqlInit();
				if (_mysql == NULL) {
					exit(-1);
				}
			}
			// 释放msyql操作句柄
			~TableVideo() {
				MysqlDestroy(_mysql);
			}
			// 新增-传⼊视频信息
			bool Insert(const Json::Value &video) {
				//id name视频名 info视频简介 video视频路径 image图片路径
				std::string sql;
				sql.resize(4096 + video["info"].asString().size());//防止简介过长
				#define INSERT_VIDEO "insert tb_video values(null, '%s', '%s', '%s', '%s');"
				//可以对各个数据增加校验，去增加各种规则，比如视频名不能没有 等等等
				if (video["name"].asString().size() == 0) {
					return false;
				}
				//要完成的细致的话需要对各个数据进行校验，因为不校验直接用就有可能出问题
				sprintf(&sql[0], INSERT_VIDEO, video["name"].asCString(),
						video["info"].asCString(), 
						video["video"].asCString(),
						video["image"].asCString());
				return MysqlQuery(_mysql, sql);
			}
			// 修改-传⼊视频id，和信息
			bool Update(int video_id, const Json::Value &video) {
				std::string sql;
				sql.resize(4096 + video["info"].asString().size());//防止简介过长
				#define UPDATE_VIDEO "update tb_video set name='%s', info='%s' where id=%d;"
				sprintf(&sql[0], UPDATE_VIDEO, video["name"].asCString(),
						video["info"].asCString(), video_id);
				return MysqlQuery(_mysql, sql);
			}
			// 删除-传⼊视频ID
			bool Delete(int video_id) {
				#define DELETE_VIDEO "delete from tb_video where id=%d;"
				char sql[1024] = {0};
				sprintf(sql, DELETE_VIDEO, video_id);
				return MysqlQuery(_mysql, sql);
			}
			// 查询所有--输出所有视频信息
			bool SelectAll(Json::Value *videos) {
				#define SELECTALL_VIDEO "select * from tb_video;"
				_mutex.lock();//-----lock start 保护查询与保存结果到本地的过程
				bool ret = MysqlQuery(_mysql, SELECTALL_VIDEO);
				if (ret == false) {
					_mutex.unlock();
					return false;
				}
				//保存查询结果集
				MYSQL_RES *res = mysql_store_result(_mysql);
				if (res == NULL) {
					std::cout << "mysql store result failed!\n";
					_mutex.unlock();
					return false;
				}
				_mutex.unlock();//------lock end
				//查看结果有多少行，并传入vidows中
				int num_rows = mysql_num_rows(res);
				for (int i = 0; i < num_rows; i++) {
					MYSQL_ROW row = mysql_fetch_row(res);//取出一条结果
					Json::Value video;
					video["id"] = atoi(row[0]);
					video["name"] = row[1];
					video["info"] = row[2];
					video["video"] = row[3];
					video["image"] = row[4];
					videos->append(video);
				}
				mysql_free_result(res);//释放结果集
				return true;
			}
			// 查询单个-输⼊视频id, 输出信息
			bool SelectOne(int video_id, Json::Value *video) {
				#define SELECTONE_VIDEO "select * from tb_video where id=%d;"
				char sql[1024] = {0};
				sprintf(sql, SELECTONE_VIDEO, video_id);
				_mutex.lock();//-----lock start 保护查询与保存结果到本地的过程
				bool ret = MysqlQuery(_mysql, sql);
				if (ret == false) {
					_mutex.unlock();
					return false;
				}
				//保存查询结果集
				MYSQL_RES *res = mysql_store_result(_mysql);
				if (res == NULL) {
					std::cout << "mysql store result failed!\n";
					_mutex.unlock();
					return false;
				}
				_mutex.unlock();//------lock end
				//查看结果有多少行，并传入vidows中
				int num_rows = mysql_num_rows(res);
				if (num_rows != 1) {
					std::cout << "have no data!\n";
					mysql_free_result(res);
					return false;
				}
				MYSQL_ROW row = mysql_fetch_row(res);//取出一条结果
				(*video)["id"] = video_id;
				(*video)["name"] = row[1];
				(*video)["info"] = row[2];
				(*video)["video"] = row[3];
				(*video)["image"] = row[4];
				mysql_free_result(res);//释放结果集
				return true;
			}
			// 模糊匹配 - 输⼊名称关键字，输出视频信息
			bool SelectLike(const std::string &key, Json::Value *videos){
				#define SELECTLIKE_VIDEO "select * from tb_video where name like '%%%s%%';"
				char sql[1024] = {0};
				sprintf(sql, SELECTLIKE_VIDEO, key.c_str());
				_mutex.lock();//-----lock start 保护查询与保存结果到本地的过程
				bool ret = MysqlQuery(_mysql, sql);
				if (ret == false) {
					_mutex.unlock();
					return false;
				}
				MYSQL_RES *res = mysql_store_result(_mysql);
				if (res == NULL) {
					std::cout << "mysql store result failed!\n";
					_mutex.unlock();
					return false;
				}
				_mutex.unlock();//------lock end
				int num_rows = mysql_num_rows(res);
				for (int i = 0; i < num_rows; i++) {
					MYSQL_ROW row = mysql_fetch_row(res);
					Json::Value video;
					video["id"] = atoi(row[0]);
					video["name"] = row[1];
					video["info"] = row[2];
					video["video"] = row[3];
					video["image"] = row[4];
					videos->append(video);
				}
				mysql_free_result(res);
				return true;
			}
	};
}

#endif
